'''
Created on 09/10/2012

@author: rcasal
'''
import datetime
from dateutil import parser
from dateutil.parser import *
from repositories.i_repository import IRepository
from gluon.dal import Field
from gluon.validators import IS_NOT_IN_DB, IS_NOT_EMPTY, IS_IN_DB, IS_EMPTY_OR,\
    IS_INT_IN_RANGE, IS_LENGTH, IS_EMAIL, IS_IN_SET
import datetime

from domain.entities.comunicacion import ModoComunicacion, Condicion,\
    Comunicacion
from repositories.afiliaciones.afiliado import SEXOS

class CondicionRepository(IRepository):
    '''
    classdocs
    '''
    
    @property
    def tabla(self):
        return self.__table

    def __init__(self, sigecon, T):
        '''
        Constructor
        '''
        self.__sigecon = sigecon
        self.__table = None
        self.__T = T
        
    def define_table(self, migrate = False):
        
        self.__sigecon.define_table('TiposConsultantes'
        ,Field('descripcion', type = 'string', length = 50, unique = True, required = True, notnull = True)
        , migrate = migrate
        )
        self.__table = self.__sigecon['TiposConsultantes']
        self.add_requires()
        
    def add_requires(self):
        self.__table.descripcion.requires = [IS_NOT_IN_DB(self.__sigecon, self.__sigecon.TiposConsultantes.descripcion), IS_NOT_EMPTY()]
            
    def findOne(self, ident, asdict = False):
        condicion = Condicion()
        res = self.__sigecon(self.__sigecon.TiposConsultantes.id == ident).select().last()
        if res:
            condicion.ID = res.id
            condicion.descripcion = res.descripcion
        else:
            condicion = None
        return condicion
    
    def findAll(self, asdict = False):
        res = self.__sigecon(self.__sigecon.TiposConsultantes.id > 0).select()
        if asdict:
            return res
        raise NotImplementedError()
    
    def save(self, entity):
        raise NotImplementedError()
    
    def delete(self, entity):
        raise NotImplementedError()
    
    def update(self, entity):
        raise NotImplementedError()
    
class ModalidadRepository(IRepository):
    '''
    classdocs
    '''
    @property
    def tabla(self):
        return self.__table
    
    def __init__(self, sigecon, T):
        '''
        Constructor
        '''
        self.__sigecon = sigecon
        self.__table = None
        self.__T = T
        
    def define_table(self, migrate = False):
        
        self.__sigecon.define_table('ModalidadesComunicacion'
        ,Field('descripcion', type = 'string', length = 50, unique = True, required = True, notnull = True)
        , migrate = migrate
        )
        self.__table = self.__sigecon['ModalidadesComunicacion']
        self.add_requires()
        
    def add_requires(self):
        self.__table.descripcion.requires = [IS_NOT_IN_DB(self.__sigecon, self.__sigecon.ModalidadesComunicacion.descripcion), IS_NOT_EMPTY()]
            
    def findOne(self, ident):
        modo = None
        res = self.__sigecon(self.__sigecon.ModalidadesComunicacion.id == ident).select().last()
        if res:
            modo = ModoComunicacion()
            modo.ID = res.id
            modo.descripcion = res.descripcion
        return modo
    
    def findAll(self):
        raise NotImplementedError()
    
    def save(self, entity):
        raise NotImplementedError()
    
    def delete(self, entity):
        raise NotImplementedError()
    
    def update(self, entity):
        raise NotImplementedError()
    
    def findByDescripcion(self, descripcion):
        modo = None
        res = self.__sigecon(self.__sigecon.ModalidadesComunicacion.descripcion == descripcion).select().last()
        if res:
            modo = ModoComunicacion()
            modo.ID = res.id
            modo.descripcion = res.descripcion
        return modo
    
class ComunicacionRepository(IRepository):
    '''
    classdocs
    '''
    @property
    def tabla(self):
        return self.__table
    
    def __init__(self, sigecon, datoscomunes, auth, T):
        '''
        Constructor
        '''
        self.__sigecon = sigecon
        self.__datoscomunes = datoscomunes
        self.__auth = auth
        self.__table = None
        self.__T = T
        
    def define_table(self, migrate = False):
        
        self.__sigecon.define_table('Comunicaciones'
        ,Field('modalidad', type = 'reference ModalidadesComunicacion', length = 8, required = True, notnull = True, writable = False, readable = False)
        ,Field('condicion', type = 'reference TiposConsultantes', length = 4, required = True, notnull = True)
        ,Field('nombre', type = 'string', length = 50, required = True, notnull = True, label = 'Nombre')
        ,Field('genero', type = 'integer', label = 'Sexo')
        ,Field('tipo_documento', type = 'integer', length = 4, label = 'Tipo doc')
        ,Field('nro_documento', type = 'integer', length = 4, label = 'Nro doc')
        ,Field('cuit', type = 'string', length = 11, required = True, label = 'CUIT')
        ,Field('cuil', type = 'string', length = 11, required = True, label = 'CUIL')
        ,Field('telefono', type = 'string', length = 50, required = True, label = 'Telefono')
        ,Field('mail', type = 'string', length = 50, required = True, label = 'Mail')
        ,Field('provincia',   type = 'integer', length = 4)
        ,Field('localidad',  type = 'integer', length = 4)
        ,Field('departamento', type = 'integer', length = 4, writable = False, readable = False)
        ,Field('barrio', type = 'integer')
        ,Field('creado_en', type = 'datetime', default = datetime.datetime.now(), update = datetime.datetime.now(), writable = False, readable = False, notnull = True)
        ,Field('usuario', type = 'reference auth_user', default = self.__auth.user_id, writable = False, readable = False, required = True, notnull = True)
        ,migrate = migrate
        )
        self.__table = self.__sigecon['Comunicaciones']
        self.add_requires()
        
    def add_requires(self):
        self.__table.modalidad.requires = IS_IN_DB(self.__sigecon, self.__sigecon.ModalidadesComunicacion.id,'%(descripcion)s', zero = self.__T('choose one'))
        self.__table.condicion.requires = IS_IN_DB(self.__sigecon, self.__sigecon.TiposConsultantes.id, '%(descripcion)s', zero = self.__T('choose one'))
        self.__table.nombre.requires = [IS_NOT_EMPTY(self.__T('no puede ser vacio')), IS_LENGTH(50,1)]
#        self.__table.provincia.requires = IS_IN_DB(self.__datoscomunes, self.__datoscomunes.ProvinciasView.id,'%(Name)s')
#        self.__table.localidad.requires = IS_IN_DB(self.__datoscomunes, self.__datoscomunes.Localidades.id,'%(Nombre)s')
#        self.__table.tipo_documento.requires = IS_IN_DB(self.__datoscomunes, self.__datoscomunes.CodTipoDocumento.id, '%(Codigo)s', orderby = 'CodTipoDocumento.Codigo ASC', zero = self.__T('choose one'))        
#        self.__table.genero.requires = IS_IN_SET(SEXOS, zero = self.__T('choose one'))
#    
    def add_represents(self):
        #dbSIGECON.Consultas.FechaHoraFin.represent = lambda fecha: fecha.strftime("%d/%m/%Y %H:%M")
        #dbSIGECON.Consultas.FechaHoraInicio.represent = lambda fecha: fecha.strftime("%d/%m/%Y %H:%M")
        #dbSIGECON.Consultas.ID_Origen.represent = lambda id: dbAdmin(dbAdmin.auth_group.id == id).select(dbAdmin.auth_group.role)[0].role if id > 0 else "sin datos"
        #dbSIGECON.Consultas.ID_Sexo.represent = lambda id: SEXOS[str(id)] if id > 0 else ""
        #dbSIGECON.Consultas.ID_Provincia.represent = lambda id: dbDatosComunes(dbDatosComunes.Provincias.Prefijo == id).select(dbDatosComunes.Provincias.Nombre)[0].Nombre if id != None else "sin datos"
        #def nombreLocalidad(idLocalidad):
        #    if idLocalidad == 0 or idLocalidad == None:
        #        return "sin datos"
        #    elif len(Persistor().localidadXId (idLocalidad)) > 0:
        #        return dbDatosComunes(dbDatosComunes.Localidades.id == idLocalidad).select(dbDatosComunes.Localidades.Nombre)[0].Nombre
        #    else:
        #        return "Capital Federal"
        #dbSIGECON.Consultas.ID_Localidad.represent = lambda idLocalidad: nombreLocalidad(idLocalidad)
        #dbSIGECON.Consultas.ID_Departamento.represent = lambda id: dbDatosComunes(dbDatosComunes.Departamentos.id == id).select(dbDatosComunes.Departamentos.Nombre)[0].Nombre if id != None else "sin datos"
        #def nombreBarrio(idBarrio):
        #    reg = dbSIGECON(dbSIGECON.Barrios.id == idBarrio).select(dbSIGECON.Barrios.Nombre)
        #    if idBarrio == 0 or idBarrio == None:
        #        return "sin datos"
        #    elif len(reg) > 0:
        #        return reg[0].Nombre
        #    else:
        #        return "no encontrado"
        #dbSIGECON.Consultas.ID_Barrio.represent = lambda idBarrio: nombreBarrio(idBarrio)
        #dbSIGECON.Consultas.ID_Usuario.represent =  lambda id: dbAdmin.auth_user(id).first_name if id > 0 else ""
        #dbSIGECON.Consultas.TipoDoc.represent =  lambda id: dbDatosComunes(dbDatosComunes.CodTipoDocumento.id == id).select(dbDatosComunes.CodTipoDocumento.Codigo)[0].Codigo if id != None else "sin datos"
        #dbSIGECON.Consultas.ID_Sector.represent = lambda id: dbSIGECON.Sectores(id).Descripcion if id > 0 else ""
        #dbSIGECON.Consultas.ID_TipoConsultante.represent = lambda id: dbSIGECON(dbSIGECON.TiposConsultantes.id == id).select(dbSIGECON.TiposConsultantes.Descripcion)[0].Descripcion if id != None else "sin datos" 

        pass
    
    def refresh_requires(self, comunicacion):
        descripcion = comunicacion.modalidad.descripcion
        if descripcion == "TELEFONICA":
            self.__requires_modalidad_telefonica(comunicacion)
        elif descripcion == "MAIL":
            self.__requires_modalidad_mail(comunicacion)
        elif descripcion == "PERSONAL":
            self.__requires_modalidad_telefonica(comunicacion)
        else:
            raise Exception("no se establecio el modo de consulta")
    
    def __requires_modalidad_telefonica(self, comu):
        dbComunes = self.__datoscomunes
        comunicacion = Comunicacion
        comunicacion = comu
        
        ###
        self.__table.genero.requires = IS_IN_SET(SEXOS, zero = self.__T('choose one'))
        self.__table.tipo_documento.requires = IS_IN_DB(self.__datoscomunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Codigo ASC', zero = self.__T('choose one'))        
        
        ### la provincia es obligatoria siempre
        self.__table.provincia.requires = IS_IN_DB(dbComunes, dbComunes.ProvinciasView.id,'%(Name)s', zero = self.__T('choose one'))
        
        if comunicacion.provincia == None or comunicacion.provincia.ID == None:
            ### si no se cargo la provincia localidad y barrio aparecen vacios
            self.__table.localidad.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
            self.__table.departamento.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
            self.__table.barrio.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
        else:
            self.__table.localidad.requires = IS_IN_DB(dbComunes((dbComunes.ProvinciasView.id == comunicacion.provincia.ID) & (dbComunes.Departamentos.Provincia == dbComunes.ProvinciasView.Pref) & (dbComunes.Localidades.IDDepartamento == dbComunes.Departamentos.id)), 'Localidades.id', '%(Nombre)s', orderby = 'Localidades.Nombre ASC', zero = self.__T('choose one')) 
            if comunicacion.provincia.nombre == 'Capital Federal':
                self.__table.barrio.requires = IS_IN_DB(dbComunes, 'Barrios.id', '%(Nombre)s', orderby = 'Barrios.Nombre ASC', zero = self.__T('choose one'))
            else:
                self.__table.barrio.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
        
        ### debe ingresar un dato de contacto telefono o mail
        if comunicacion.telefono == '' and comunicacion.mail == '':
            self.__table.telefono.requires = IS_NOT_EMPTY(error_message = self.__T('agregar telefono o mail'))
            self.__table.mail.requires = IS_NOT_EMPTY(error_message = self.__T('agregar telefono o mail'))
        elif comunicacion.mail != '':
            self.__table.mail.requires = IS_EMAIL()
                
                
        if comunicacion.condicion != None:
            descripcion = comunicacion.condicion.descripcion
            if descripcion == 'AFILIADO':
                self.__table.cuit.requires = []
                self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
                self.__table.tipo_documento.requires = IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Codigo ASC', zero = self.__T('choose one'))        
                self.__table.nro_documento.requires = IS_INT_IN_RANGE(100, 99000000)
                self.__table.cuil.requires = IS_NOT_EMPTY() 
            elif descripcion == 'NO AFILIADO':
                self.__table.genero.requires = IS_IN_SET(SEXOS, zero = self.__T('choose one'))
                self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Descripcion ASC', zero = self.__T('choose one')))        
                self.__table.nro_documento.requires = IS_EMPTY_OR(IS_INT_IN_RANGE(100, 99000000))
                self.__table.cuil.requires = []
            elif descripcion == 'EMPLEADOR':
                self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET(SEXOS, zero = self.__T('choose one')))
                self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Descripcion ASC', zero = self.__T('choose one')))        
                self.__table.nro_documento.requires = IS_EMPTY_OR(IS_INT_IN_RANGE(100, 99000000))
                self.__table.cuit.requires = IS_INT_IN_RANGE(1, None)
                self.__table.cuil.requires = []
            elif descripcion == 'PRESTADOR':
                self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET(SEXOS, zero = self.__T('choose one')))
                self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Descripcion ASC', zero = self.__T('choose one')))        
                self.__table.nro_documento.requires = IS_EMPTY_OR(IS_INT_IN_RANGE(100, 99000000))
                self.__table.cuit.requires = IS_INT_IN_RANGE(1, None)
                self.__table.cuil.requires = []
            pass
        
    def __requires_modalidad_mail(self, comu):
        dbComunes = self.__datoscomunes
        comunicacion = Comunicacion()
        comunicacion = comu
        
        ###
        self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET(SEXOS, zero = self.__T('choose one')))
        self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(self.__datoscomunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Codigo ASC', zero = self.__T('choose one')))        
        
        ### la provincia es obligatoria siempre
        self.__table.provincia.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, dbComunes.ProvinciasView.id,'%(Name)s', zero = self.__T('choose one')))
        
        if comunicacion.provincia == None or comunicacion.provincia.ID == None:
            ### si no se cargo la provincia localidad y barrio aparecen vacios
            self.__table.localidad.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
            self.__table.departamento.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
            self.__table.barrio.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
        else:
            self.__table.localidad.requires = IS_IN_DB(dbComunes((dbComunes.ProvinciasView.id == comunicacion.provincia.ID) & (dbComunes.Departamentos.Provincia == dbComunes.ProvinciasView.Pref) & (dbComunes.Localidades.IDDepartamento == dbComunes.Departamentos.id)), 'Localidades.id', '%(Nombre)s', orderby = 'Localidades.Nombre ASC', zero = self.__T('choose one')) 
            if comunicacion.provincia.nombre == 'Capital Federal':
                self.__table.barrio.requires = IS_IN_DB(dbComunes, 'Barrios.id', '%(Nombre)s', orderby = 'Barrios.Nombre ASC', zero = self.__T('choose one'))
            else:
                self.__table.barrio.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
        
        ### el mail es obligatorio
        self.__table.mail.requires = IS_EMAIL()
                
        if comunicacion.condicion != None:
            descripcion = comunicacion.condicion.descripcion
            if descripcion == 'AFILIADO':
                self.__table.cuit.requires = []
                self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET([], zero = self.__T('choose one')))
                self.__table.tipo_documento.requires = IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Codigo ASC', zero = self.__T('choose one'))        
                self.__table.nro_documento.requires = IS_INT_IN_RANGE(100, 99000000)
                self.__table.cuil.requires = IS_NOT_EMPTY() 
            elif descripcion == 'NO AFILIADO':
                self.__table.genero.requires = IS_IN_SET(SEXOS, zero = self.__T('choose one'))
                self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Descripcion ASC', zero = self.__T('choose one')))        
                self.__table.nro_documento.requires = IS_EMPTY_OR(IS_INT_IN_RANGE(100, 99000000))
                self.__table.cuil.requires = []
            elif descripcion == 'EMPLEADOR':
                self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET(SEXOS, zero = self.__T('choose one')))
                self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Descripcion ASC', zero = self.__T('choose one')))        
                self.__table.nro_documento.requires = IS_EMPTY_OR(IS_INT_IN_RANGE(100, 99000000))
                self.__table.cuit.requires = IS_INT_IN_RANGE(1, None)
                self.__table.cuil.requires = []
            elif descripcion == 'PRESTADOR':
                self.__table.genero.requires = IS_EMPTY_OR(IS_IN_SET(SEXOS, zero = self.__T('choose one')))
                self.__table.tipo_documento.requires = IS_EMPTY_OR(IS_IN_DB(dbComunes, 'CodTipoDocumento.id', '%(Codigo)s', orderby = 'CodTipoDocumento.Descripcion ASC', zero = self.__T('choose one')))        
                self.__table.nro_documento.requires = IS_EMPTY_OR(IS_INT_IN_RANGE(100, 99000000))
                self.__table.cuit.requires = IS_INT_IN_RANGE(1, None)
                self.__table.cuil.requires = []
            pass
        
    def findOne(self, ident):
        fields =  self.__sigecon(self.__sigecon.Comunicaciones.id == ident).select().last() 
        if fields:
            return Comunicacion.deserialize(fields)
        return None
    
    def findLastByUserId(self, userid):
        fields =  self.__sigecon(self.__sigecon.Comunicaciones.usuario == userid).select().last() 
        if fields:
            return Comunicacion.deserialize(fields)
        return None
    
    def findAllByUserId(self, userid, asdict = False):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.usuario == userid).select() 
        if asdict == True:
            return resultado
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByCondicion(self, condicionid, asdict = False):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.condicion == condicionid).select() 
        if asdict == True:
            return resultado
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByNombre(self, nombre, asdict = False):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.nombre.like('%'+nombre+'%')).select(orderby = 'Comunicaciones.id DESC') 
        if asdict == True:
            return resultado
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByTelefono(self, telefono):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.telefono == telefono).select(orderby = 'Comunicaciones.id DESC') 
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByMail(self, mail):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.mail == mail).select(orderby = 'Comunicaciones.id DESC') 
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByCuit(self, cuit):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.cuit == cuit).select(orderby = 'Comunicaciones.id DESC') 
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByCuil(self, cuil):
        resultado =  self.__sigecon(self.__sigecon.Comunicaciones.cuil == cuil).select(orderby = 'Comunicaciones.id DESC') 
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
        return comunicaciones
    
    def findAllByProvincia(self, provinciaid, asdict = True):
        fields =  self.__sigecon(self.__sigecon.Comunicaciones.provincia == provinciaid).select() 
        if asdict == True:
            return fields
        raise NotImplementedError()
    
    
    def findByDate(self, fechaDesde, fechaHasta = None, asdict = True): 
        pfechaDesde = parse("00:00:00", default=fechaDesde)
        if(fechaHasta == None):
            pfechaHasta = parse("23:59:59", default=fechaDesde)   
        else:
            pfechaHasta = parse("23:59:59", default=fechaHasta)
            
        resultado =self.__sigecon((self.__sigecon.Comunicaciones.creado_en >= pfechaDesde) & (self.__sigecon.Comunicaciones.creado_en <= pfechaHasta)).select(orderby = 'Comunicaciones.id ASC')  
        if asdict == True:
            return resultado
        comunicaciones = []
        for fields in resultado:
            comunicaciones.append(Comunicacion.deserialize(fields))
            return comunicaciones
    
    def findAll(self):
        raise NotImplementedError()
    
    def save(self, fields):
        return self.__table.insert(**self.__table._filter_fields(fields))
    
    def delete(self, entity):
        raise NotImplementedError()
    
    def update(self, entity):
        raise NotImplementedError()